home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / Tutorials / Gadgets < prev    next >
Text File  |  1989-05-30  |  37KB  |  981 lines

  1.  
  2.  
  3.                     PHUN WITH GADGETS - John T. Draper
  4.                     ----------------------------------
  5.  
  6. Feel free to distribute this information onto any network.  Please check 
  7. first to avoid duplication.  Would at least like credit for the 20 hours or 
  8. so I took in preparing this section.
  9.  
  10. Gadgets are multi function input "devices" which run under Intuition.  There 
  11. are four kinds, and two flavors.
  12.  
  13. The flavors are:
  14.  
  15. 1) System gadgets - Those created for you when you create a window or screen
  16.  
  17. 2) User gadgets - Those gadgets YOU create and use in your program.  There 
  18.    are four kinds of these.
  19.  
  20.  
  21. The four kinds are:
  22.  
  23. 1) Boolean Gadgets - Usually "Yes/no" desisions,  "On/Off" buttons,  and 
  24.    other related uses.   They look like rectangles,  with text displayed (Or 
  25.    rendered), within those rectangles.
  26.  
  27. 2) Proportional Gadgets - Those which look like "Sliders" as displayed in the 
  28.    "R G B" Controls in the "Preferences" program.  I think Amiga should 
  29.    release the source to Preferences,  because It would be a very good 
  30.    example program.
  31.  
  32. 3) String gadgets - These allow text entry through the Keyboard.  Text can be 
  33.    automatically centered.
  34.  
  35. 4) Integer Gadget - A special form of string gadget that converts numeric 
  36.    text input into integers.
  37.  
  38.  
  39. USING GADGETS
  40. -------------
  41.  
  42. Each gadget has a data structure "Gadget",  which must first be declared and 
  43. initialized.  There are several ways to do this.   The easiest way is to 
  44. declare and initialize them like this:
  45.  
  46.   
  47. #define BLUE_GADGET 0         /* My own Gadget ID to mean this gadget */
  48. struct Gadget blue_gad = {
  49.    NL, 17,112, 150,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  50.    PROPGADGET,(APTR)&b_img, NL,
  51.    &btxt, NL,(APTR)&b_prop, BLUE_GADGET, NL
  52. };
  53.  
  54.  
  55. #define GREEN_GADGET 1        /* Another personal ID */
  56. struct Gadget green_gad = {
  57.    &blue_gad, 17,97, 120,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  58.    PROPGADGET,(APTR)&g_img, NL,
  59.    >xt, NL,(APTR)&g_prop, GREEN_GADGET, NL
  60. };
  61.  
  62.  
  63. #define RED_GADGET 2          /* And yet another gadget */
  64. struct Gadget red_gad = {
  65.    &green_gad, 17,82, 90,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  66.    PROPGADGET,(APTR)&r_img, NL,
  67.    &rtxt, NL,(APTR)&r_prop, RED_GADGET, NL
  68. };
  69.  
  70.  
  71. #define TEX_GAD 3
  72. struct Gadget tex_gad = {
  73.    &red_gad, 10,10, 150,11, GADGHCOMP, STRINGCENTER | LONGINT,
  74.    STRGADGET, NL, NL,
  75.    NL, NL, (APTR)&TexString, TEX_GAD, NL
  76. };
  77.  
  78. The #define BLUE_GADGET 0,  etc,  are my own personal numbers that I want to 
  79. use to identify these gadgets in my very own personal way.  I am using them 
  80. for identification and to take action when the gadget is chosen via a C 
  81. "Switch" statement.
  82.  
  83. Each "Element" in the structures declared above are separated by commas (For 
  84. those not familiar with C),  and will be explained in detail.  In the above 
  85. examples are Three Proportional Gadgets,  and a Text Gadget.  A more detailed 
  86. description of each of the gadget fields are listed below.  It is pretty well 
  87. explained in the Intuition manual.   Just a lack of examples showing how to 
  88. build and detect them.
  89.  
  90. -- (NextGadget) First element is the "link" to the next gadget.  Last gadget
  91.    has a Null (NL) for a link.  Note,  the last gadget is on the top.  The
  92.    LAST Gadget should be set to NULL (NL).
  93.  
  94. -- (LeftEdge, TopEdge) - Specifies the LOCATION of the gadget relative to the
  95.    window or screen,  in the above example,  "tex_gad.LeftEdge" has the 
  96.    value of 10.  The last gadget has LeftEdge = 17, TopEdge = 112 as shown
  97.    above.
  98.  
  99. -- (Width, Height) - Specifies the Width and the height of the gadget select
  100.    box.  In the above example,  the height remained the same,  and the Width
  101.    progressively got smaller.  Width = 150, Height = 11 on the last one,
  102.    then Width = 120, then eventually 90, See above.
  103.  
  104. -- (Flags) - Flags that you share with Intuition.to describe the appearance 
  105.    and behavior of the gadget.  GADGHCOMP is a flag that complements all
  106.    of the bits contained within the gadget's select box.
  107.  
  108. -- (Activation) - Other flags that are used to activate certain features of
  109.    the gadget.  GADGIMMEDIATE | RELVERIFY mean that we set BOTH those "Bits".
  110.  
  111. -- (GadgetType) - Describes the type of gadget.  In the example above,
  112.    STRGADGET is one of the four types of gadgets that describe "string" or
  113.    "Text".
  114.  
  115. -- (GadgetRender) - Points to an intuiImage.  This is what gets written onto
  116.    screen or window as the gadget.  In the case where we use the proportional
  117.    gadget, we supply the address of the Image Structure without initializing
  118.    it.  It then gets rendered as a rectangle.
  119.  
  120. -- (SelectRender) - In this example, we put a NULL (NL) in this field.  If
  121.    we wanted, we could put in another image.  This image would be displayed
  122.    during highlighting (When mouse button is pressed in the gadget's select
  123.    box).
  124.  
  125. -- (GadgetText) - A pointer to an "Intuitext" structure that describes any 
  126.    text that might be rendered when the gadget is rendered.
  127.  
  128. -- (MutualExclude) - In this example, we place a NULL (NL).  There are 32
  129.    bits that can be used to "Turn off" other gadgets if this gadget gets
  130.    selected.
  131.  
  132. -- (SpecialInfo) - A pointer to more information about proportional (PropInfo)
  133.    and text (StringInfo).
  134.    gadgets.
  135.  
  136. -- (GadgetID) - User definable ID Field.  It can be used to identify the
  137.    gadget from the gadget pointer.  I use it as an argument to the
  138.    "switch" statement,  because using an address (Or any large number) as
  139.    arguments to the "switch" statement will cause the system to crash.
  140.    It's a bug in the Lattice C compiler.
  141.  
  142. -- (UserData) - A pointer to data that can be of any user definable
  143.    structure or data.
  144.  
  145. There are other structures needed for gadgets which are "SpecialInfo" types 
  146. of structures.  They are: PropInfo, and StringInfo structures. These describe 
  147. in detail more information on Proportional structures and Text structures.  
  148. Addresses of these structures will be put in the "SpecialInfo" field of the 
  149. gadget structure.  For instance,  in the example above where the gadgets are 
  150. declared and initialized, (APTR)&r_img is used in the "red_gad" declaration.  
  151. Where "r_img" is declared as follows:
  152.  
  153. struct Image    r_img, g_img, b_img;
  154.  
  155. In this particular example,  these are Images used by Intuition.  Sometimes 
  156. YOU have to declare your own image.  Other times,  such as in the case above, 
  157. Intuition initializes these images.  On first reading of the Intuition 
  158. manual, it is not evident that These are initialized.
  159.  
  160.  
  161.  
  162.  
  163. PropInfo Structure:
  164. -------------------
  165.  
  166. A PropInfo structure contains specific information about a proportional 
  167. gadget.  Such as a slider arm,  or a volume control.  
  168.  
  169. -- (flags) - A set of flags like:
  170.  
  171.    AUTOKNOB - If you want to use a generic default knob.  It's essentually
  172.    a rectangle that fills the body of the proportional gadget.  If you set
  173.    this flag,  Intuition will initialize the rest of this structure.
  174.    A piece of code in the Example GAD.C shows where Three proportional
  175.    structures are initialized.  These structures are named:
  176.    "r_prop", "g_prop", and "b_prop".
  177.  
  178. /***************************************************************************
  179.            Must Initialize the Proportional "Specialinfo" before
  180.       opening up the window.  Init Flags,  and position.
  181. ***************************************************************************/
  182.  
  183.    r_prop.Flags = g_prop.Flags = b_prop.Flags = FREEHORIZ | AUTOKNOB;
  184.    r_prop.HorizBody = g_prop.HorizBody = b_prop.HorizBody = 0x1000;
  185.    r_prop.HorizPot = g_prop.HorizPot = b_prop.HorizPot = 0x8000;
  186.  
  187.  
  188.    FREEHORIZ - Set this flag if you only want the "slider" or "Pot" to
  189.    slide horizontally.
  190.  
  191.    FREEVERT - Set this flag if you want to slide vertically only.
  192.  
  193.    PROPBORDERLESS - Set this flag if you don't want borders.
  194.  
  195.    KNOBHIT - Check this flag if you want to know if the mouse button is
  196.    on the knob.
  197.  
  198.    For example,  if you want a standard slider which is horizontally placed
  199. in the window,  set the flags:  AUTOKNOB | FREEHORIZ
  200.  
  201.    If you are using a custom gadget, for instance a "joystick" that can move
  202. BOTH horizontally and vertically like the source code example in this lesson.
  203. then set the flags:  FREEHORIZ | FREEVERT.
  204.  
  205. -- (HorizPot) - Horizontal Position value for the gadget.
  206.  
  207. -- (VertPot)  - Vert Position value for the gadget.
  208.  
  209. -- (horizBody) - The incremental width of the gadget.  If set to 0x1000,
  210.    means that the pot will move 1/16th of the full position if the mouse
  211.    was pressed between the slider and the side of the gadget.  it always
  212.    moves "towards" the point where the mouse was pressed.  The "joystick" 
  213.    custom gadget in the example sort of "Follows" the mouse.
  214.  
  215. -- (VertBody) - Vertical incremental width of the gadget.
  216.  
  217.    The following fields are set by Intuition and are accessable to the 
  218. user if needed.
  219.  
  220. -- (cWidth) - Container width.
  221.  
  222. -- (cHeight) - Container height.
  223.  
  224. -- (HPotRes, VPotRes) - Horiz and Vert increments.
  225.  
  226. -- (LeftBorder, TopBorder) - Container borders.
  227.  
  228.    Here is a PropInfo structure for a custom designed joystick.
  229.  
  230. struct PropInfo cust_prop = {
  231.    FREEHORIZ | FREEVERT,            /* Want knob to go both vert and horiz */
  232.    0x8000,  0x8000,                 /* Want knob to be centered initially  */
  233.    0x800,   0x800,                  /* Smallest increment the knob can move */
  234.    150, 50,                         /* cWidth, cHeight - Container w & h */
  235.    1, 1,                            /* HPosres, VPotres - Pot increments */
  236.    0, 0                             /* Container borders  */
  237. };
  238.  
  239. You can stick this anywhere in the global declarations section of your 
  240. program.  Because of the limitations of the Lattice C compiler,  It should be 
  241. declared "Before" the Gadget structure that uses it.
  242.  
  243. An important thing to remember about constructing gadgets is that the 
  244. Coordinates in the Gadget structure are relative to the coordinates in the 
  245. Window or Screen.
  246.  
  247. The coordinates in the border, or intuitext structure used by gadgets are 
  248. RELATIVE to the Gadgets and NOT the window.  For instance,  if you want text 
  249. to be displayed OVER the gadget rectangle,  your Y coords will be about -8 to 
  250. -10,  while your x coords will be positive.  The point where text is written 
  251. is at the UPPER LEFT section of the letters and NOT the lower left portion of 
  252. the letters like in the Macintosh.
  253.  
  254. If you use borders around your gadgets, make sure you make room for at least 
  255. one pixel around the "Selection box".  Because, when the user presses in the 
  256. box,  it is inversed, and if the border coincides with a pixel in the 
  257. selection box,   that pixel overlaps and turns into another color, thus 
  258. making it look a bit cludgey.
  259.  
  260.  
  261.  
  262. HOW TO CREATE GADGETS IN YOUR PROGRAM
  263. -------------------------------------
  264.  
  265. FIRST OFF - Sketch out an approximate picture showing approximately what the 
  266. overall layout of the gadgets should look like.   Eventually, we will write a 
  267. Gadget Editor,   but for now,   lets make one up the old fashion way.
  268.  
  269. Define gadget structures for each gadget.  Set the gadget flags 
  270. appropriately,  specify pointers to Special structures, like "PropInfo" or 
  271. "StringInfo" structure in the "SpecialInfo" field.  If you have custom images 
  272. that you have created,   you need to declare a pointer to the image.
  273.  
  274. When you declare the gadgets,  you create the LAST gadget first in your 
  275. Source code.  Each sucessive gadget then "Links" to the one in front of it.  
  276. The last gadget pointer is a NULL.  After each of the gadgets are linked 
  277. properly,  then:
  278.  
  279. Declare any custom images,  borders,  or Text associated with the gadget.  
  280. This section of code shows an example of this.  Remember,  this portion of 
  281. code should come BEFORE any of the gadget declarations because the C compiler 
  282. doesn't seem to be able to forward reference. 
  283.  
  284. /*  Image for a custom proportional gadget */
  285.  
  286. UWORD custimage[] = {
  287. 0x0000, 0x0000, 0x0180, 0x0660, 0x1818, 0x2004, 0x4002, 0x4002,
  288. 0x4002, 0x4002, 0x2004, 0x1818, 0x0660, 0x0180, 0x0000, 0x0000
  289. };
  290.  
  291. struct Image cus_image = {
  292.   0, 0,                    /* LeftEdge, TopEdge */
  293.   16, 16, 1,               /* Width, Height, Depth */
  294.   &custimage[0],           /* Pointer to bit image */
  295.   1,  0,                   /* PlanePick, Planeonoff */
  296.   NULL                     /* No other images */
  297. };
  298.  
  299. One of the gadgets that use the above image:
  300.  
  301. #define CUST_KNOB 4
  302. struct Gadget cust_knob = {
  303.    &tex_gad, 17, 140, 150, 50, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  304.    PROPGADGET, (APTR)&cus_image, NL,
  305.    &cus2_txt, NL, (APTR)&cust_prop, CUST_KNOB, NL
  306. };
  307.  
  308. Now,  we have to make sure the very first gadget is linked to our window OR 
  309. SCREEN.  In this particular example,  we are only using a window,  and are 
  310. using the Intuition WorkBench Screen.  The NewWindow structure is declared 
  311. further down in the Code as shown below.  Making the assumption that the 
  312. gadget shown above is the FIRST gadget (last in listing),  then the New 
  313. Window structure is shown as below.
  314.  
  315. /***************************************************************************
  316. *                  N E W     W I N D O W     S T R U C T U R E
  317. ***************************************************************************/
  318.  
  319. struct NewWindow nw = {
  320.   0, 0,                  /*  Start position                               */
  321.   320, 200,              /*  width, height,                               */
  322.   0, 1,                  /*  detail, block pens                           */
  323.   CLOSEWINDOW            /*  IDCMP flags                             */
  324. | REFRESHWINDOW
  325. | MOUSEBUTTONS
  326. | MOUSEMOVE
  327. | GADGETDOWN     <--  MUST SET THIS ONE 
  328. | GADGETUP,      <--  AND THIS ONE
  329.                          /*  Regular flags for gadgets and such           */
  330.   WINDOWDEPTH
  331. | WINDOWSIZING
  332. | WINDOWDRAG
  333. | REPORTMOUSE    <-- AND THIS ONE
  334. | WINDOWCLOSE
  335. | SMART_REFRESH,
  336.  
  337.   &cust_knob,            /* First gadget in list  <-- WE DO IT HERE       */
  338.   NULL,                  /* User checkmark                                */
  339.   "Fun with Gadgets",    /* Window Title                                  */
  340.   NULL,                  /* Pointer to screen (Set later)                 */
  341.   NULL,                  /* Pointer to superbitmap                        */
  342.   0, 0, 320, 186,        /* Ignored because not sizeable                  */
  343.   WBENCHSCREEN,          /* Using the Workbench screen                    */
  344.   };
  345.  
  346.    The example program given uses a different First Gadget.  
  347.  
  348.    The last thing you should do is set the appropriate flags.  That is
  349. shown above.
  350.  
  351. RESPONDING TO THOSE GADGETS
  352. ---------------------------
  353.  
  354. Last but not least,  you need to be able to respond, read, or act on a 
  355. gadget.  This is done by "Listening" to a gadget port.  A particular bit 
  356. comes to you in a Message class field.  You must recieve this "message" from 
  357. Intuition telling you that the user "clicked" the mouse in a particular 
  358. gadget.  You don't know which one yet.  But you snatch that "message" by 
  359. detecting a certain bit in the message.class field.  You tuck this value away 
  360. for later use and "Reply" to the message, using the ReplyMsg function.  We 
  361. keep doing this over and over until the user closes the window.  This is 
  362. called an "Event loop".
  363.  
  364.  
  365. /***************************************************************************
  366.                             MAIN EVENT LOOP
  367. ***************************************************************************/
  368.  
  369.    for (;;)
  370.    {
  371.  
  372.       if (message = (struct IntuiMessage *)GetMsg(w->UserPort))  {
  373.         MessageClass = message->Class;
  374.         code = message->Code;
  375.         ReplyMsg(message);
  376.         switch (MessageClass) {
  377.  
  378.            case GADGETUP    :
  379.            case GADGETDOWN  : do_gadgets(message, w);
  380.                               break;
  381.  
  382.            case CLOSEWINDOW : close_things();
  383.                               exit(0);
  384.                               break;
  385.            case MOUSEBUTTONS: break;
  386.         }   /* Case */
  387.       }  /* if */
  388.    }  /* for */
  389. } /* main */
  390.  
  391. In the Message,  contains the Address of the gadget chosen by the user. You 
  392. pass the Message and the Window into a function called do_gadgets. This 
  393. function identifies the gadget,  then acts on it in the appropriate way.   
  394. This function is listed below.  I basically grab the address of the 
  395. particular structure,  then look for that special private code that I 
  396. described to identify the gadget.
  397.  
  398. /***************************************************************************
  399.                            HANDLE THE GADGETS
  400. ***************************************************************************/
  401. do_gadgets (mes, win)
  402.  
  403. struct IntuiMessage *mes;        /* Pointer to Message structure */
  404. struct Window *win;              /* And a window structure       */
  405. {
  406.         struct Gadget *igad;     /* Ptr to gadget that Intuition found    */
  407.         int  gadgid;             /* ID Code identifying which gadget      */
  408.         ULONG val;
  409.  
  410.      igad = (struct Gadget *) mes->IAddress;      /* Ptr to a gadget      */
  411.         gadgid = igad->GadgetID;    /* My own personal code for this gad  */
  412.         val = (ULONG)TexString.LongInt;
  413.         switch(gadgid) {
  414.  
  415.             case GREEN_GADGET: break;
  416.             case BLUE_GADGET : break;
  417.             case TEX_GAD     : printf("got here ...\n");
  418.                                printf("val = %ld\n", val);
  419.                                break;
  420.         }
  421. }
  422.  
  423. As each gadget is identified, a CASE statement selects the appropriate action 
  424. to be taken depending on the gadget.  In many cases, the SAME action is 
  425. usually performed on similar gadgets,   but in the above example,  I only 
  426. handle 3 gadgets.  I could have exampled more,  but Good ol Lattice C has a 
  427. nasty bug that won't let me use four cases without crashing.  This is why it 
  428. takes so long to write programs on the Amiga.  But thats the price for being 
  429. a pioneer.
  430.  
  431. Feel free to chop it up and hack it to death.  So gotta work on Menus 
  432. tommorrow.  Only have the Amiga for 5 more days.  Next on my aggenda for 
  433. learning is:
  434.  
  435. Menus
  436.  
  437. Requestors
  438.  
  439. Sound
  440.  
  441. This is it for now.  Have fun hacking,  and I will be back with more later.  
  442. Feel free to ask me questions,  and tell me your problems with gadgets so we 
  443. can solve them.
  444.  
  445.  
  446. /**************************************************************************
  447. *     F U N   W I T H   G A D G E T S
  448. *
  449. ***************************************************************************/
  450. #include <exec/types.h>
  451. #include <exec/nodes.h>
  452. #include <exec/lists.h>
  453. #include <exec/ports.h>
  454. #include <exec/devices.h>
  455. #include <devices/keymap.h>
  456. #include <graphics/regions.h>
  457. #include <graphics/copper.h>
  458. #include <graphics/gels.h>
  459. #include <graphics/gfxbase.h>
  460. #include <graphics/gfx.h>
  461. #include <graphics/clip.h>
  462. #include <graphics/view.h>
  463. #include <graphics/rastport.h>
  464. #include <graphics/layers.h>
  465. #include <intuition/intuition.h>
  466. #include <hardware/blit.h>
  467.  
  468. /***************************************************************************
  469.         IMPORTANT CONSTANTS
  470. ***************************************************************************/
  471. unsigned int mask = 0;            /*  ONE BIT SET FOR EACH OPEN */
  472.  
  473. #define  INTUITION   0x00000001
  474. #define  GRAPHICS    0x00000002
  475. #define  SCREEN      0x00000004
  476. #define  WINDOW      0x00000008
  477. #define  COLORMAP    0x00000010
  478. #define  MATH        0x00000020
  479. #define  MATHTRANS   0x00000040
  480.  
  481. #define NL 0
  482.  
  483. /***************************************************************************
  484. *          I N T U I T I O N      G L O B A L      V A R S
  485. ***************************************************************************/
  486.  
  487. struct IntuitionBase *IntuitionBase;
  488. struct GfxBase *GfxBase;
  489. struct IntuiMessage *message;
  490. struct RastPort *rp;
  491. struct Window *w;
  492.  
  493. /***************************************************************************
  494.             G A D G E T S      L I V E      H E R E
  495. ***************************************************************************/
  496.  
  497. /*  Image for a custom proportional gadget */
  498.  
  499. UWORD custimage[] = {
  500. 0x0000, 0x0000, 0x0180, 0x0660, 0x1818, 0x2004, 0x4002, 0x4002,
  501. 0x4002, 0x4002, 0x2004, 0x1818, 0x0660, 0x0180, 0x0000, 0x0000
  502. };
  503.  
  504. struct Image cus_image = {
  505.   0, 0,                    /* LeftEdge, TopEdge */
  506.   16, 16, 1,               /* Width, Height, Depth */
  507.   &custimage[0],           /* Pointer to bit image */
  508.   1,  0,                   /* PlanePick, Planeonoff */
  509.   NULL                     /* No other images */
  510. };
  511.  
  512.  
  513. struct IntuiText rtxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"R",NL};
  514. struct IntuiText gtxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"G",NL};
  515. struct IntuiText btxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"B",NL};
  516.  
  517. struct IntuiText ntext = {2,2,JAM1, 10, -11, NL,
  518.   (UBYTE *) "Number entry", NL};
  519.  
  520. struct IntuiText cus_text = {2,2,JAM1, 2, -11, NL,
  521.   (UBYTE *) "Custom Prop Gadget", NL};
  522.  
  523. struct IntuiText cus1_txt = {2,2,JAM1, 161, 23, NL,
  524.   (UBYTE *) "Vert side", &cus_text };
  525.  
  526. struct IntuiText cus2_txt = {2,2,JAM1, 20, 50, NL,
  527.   (UBYTE *) "Hor side", &cus1_txt };
  528.  
  529. struct IntuiText bool_str = {2,2,JAM1, 4, 1, NL,
  530.   (UBYTE *) "START", NL };
  531.  
  532. struct IntuiText bool2_str = {2,2,JAM1, 9, 1, NL,
  533.   (UBYTE *) "STOP", NL };
  534.  
  535. struct Image    r_img, g_img, b_img;
  536. struct PropInfo r_prop,g_prop,b_prop;
  537.  
  538. struct PropInfo cust_prop = {
  539.    FREEHORIZ | FREEVERT,            /* Want knob to go both vert and horiz */
  540.    0x8000,  0x8000,                 /* Want knob to be centered initially  */
  541.    0x800,   0x800,                  /* Smallest increment the knob can move */
  542.    150, 50,                         /* cWidth, cHeight - Container w & h */
  543.    1, 1,                            /* HPosres, VPotres - Pot increments */
  544.    0, 0                             /* Container borders  */
  545. };
  546.  
  547.  
  548. #define STRINGSIZE 512
  549. UBYTE DefString[STRINGSIZE] = "000000000000";
  550. UBYTE Undo [STRINGSIZE];
  551.  
  552. struct StringInfo TexString = {
  553.    DefString,                      /* Buffer - Pointer to Buffer */
  554.    Undo,                           /* UndoBuffer - Undo buf ptr  */
  555.    0,                              /* BufferPos - Init Chr Posn */
  556.    STRINGSIZE,                     /* MaxChars - Max number of Chars */
  557.    0, 0,                           /* DispPos - First Disp Chr */
  558.    13,                             /* NumChars - Number of Characters */
  559.    0, 0, 0,                        /* Posn Vars calc by Intuition */
  560.    NULL,                           /* No pointer to Rasport */
  561.    0,                              /* Longint Value */
  562.    NULL                            /* No pointer to alt Keyboard */
  563. };
  564.  
  565. USHORT Pairs[] = {
  566. -1,  -1,                            /* Information describing the */
  567. 160, -1,                           /* border around the gadget */
  568. 160, 9,
  569. -1, 9,
  570. -1, -1
  571.  };
  572.  
  573. USHORT Pairs1[] = {
  574.  0,  0,
  575. 51,  0,
  576. 51, 11,
  577. 0,  11,
  578. 0,  0
  579. };
  580.  
  581. #define NUM_PAIRS 5                /* There are Four pairs above */
  582.  
  583. struct Border StrBorder = {
  584.  -1, -1,                           /* LeftEdge, TopEdge */
  585.  1, 0, JAM1,                       /* FrontPen,  BackPen  DrawMode  */
  586.  NUM_PAIRS,                        /* Number of XY Pairs */
  587. (APTR)&Pairs,                      /* XY, Pointer to XY Pairs */
  588.  NULL                              /* No more borders */
  589. };
  590.  
  591. struct Border butt_border = {
  592.  -1, -1,
  593.  1, 0, JAM1,
  594.  NUM_PAIRS,
  595.  (APTR)&Pairs1,
  596.  NULL
  597. };
  598.  
  599. #define BLUE_GADGET 0
  600. struct Gadget blue_gad = {
  601.    NL, 17,112, 150,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  602.    PROPGADGET,(APTR)&b_img, NL,
  603.    &btxt, NL,(APTR)&b_prop, BLUE_GADGET, NL
  604. };
  605.  
  606.  
  607. #define GREEN_GADGET 1        /* Another personal ID */
  608. struct Gadget green_gad = {
  609.    &blue_gad, 17,97, 120,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  610.    PROPGADGET,(APTR)&g_img, NL,
  611.    >xt, NL,(APTR)&g_prop, GREEN_GADGET, NL
  612. };
  613.  
  614.  
  615. #define RED_GADGET 2          /* And yet another gadget */
  616. struct Gadget red_gad = {
  617.    &green_gad, 17,82, 90,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  618.    PROPGADGET,(APTR)&r_img, NL,
  619.    &rtxt, NL,(APTR)&r_prop, RED_GADGET, NL
  620. };
  621.  
  622.  
  623. #define TEX_GAD 3
  624. struct Gadget tex_gad = {
  625.    &red_gad, 30, 30, 150,11, GADGHCOMP, STRINGCENTER | LONGINT | RELVERIFY,
  626.    STRGADGET, (APTR)&StrBorder, NL,
  627.    &ntext, NL, (APTR)&TexString, TEX_GAD, NL
  628. };
  629.  
  630. #define CUST_KNOB 4
  631. struct Gadget cust_knob = {
  632.    &tex_gad, 17, 140, 150, 50, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  633.    PROPGADGET, (APTR)&cus_image, NL,
  634.    &cus2_txt, NL, (APTR)&cust_prop, CUST_KNOB, NL
  635. };
  636.  
  637. #define BOOL_GAD1 5
  638. struct Gadget bool_gad = {
  639.    &cust_knob, 30, 46, 50, 10, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  640.    BOOLGADGET, (APTR)&butt_border, NL,
  641.    &bool_str, NL, NL, BOOL_GAD1, NL
  642. };
  643.  
  644. #define BOOL_GAD2 6
  645. struct Gadget bool2_gad = {
  646.   &bool_gad, 30, 60, 50, 10, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
  647.   BOOLGADGET, (APTR)&butt_border, NL,
  648.   &bool2_str,  NL, NL, BOOL_GAD2, NL
  649. };
  650.  
  651. /***************************************************************************
  652. *                  N E W     W I N D O W     S T R U C T U R E
  653. ***************************************************************************/
  654.  
  655. struct NewWindow nw = {
  656.   0, 0,                  /*  Start position                               */
  657.   320, 200,              /*  width, height,                               */
  658.   0, 1,                  /*  detail, block pens                           */
  659.   CLOSEWINDOW            /*  IDCMP flags                             */
  660. | REFRESHWINDOW
  661. | MOUSEBUTTONS
  662. | MOUSEMOVE
  663. | GADGETDOWN
  664. | GADGETUP,
  665.                          /*  Regular flags for gadgets and such           */
  666.   WINDOWDEPTH
  667. | WINDOWSIZING
  668. | WINDOWDRAG
  669. | REPORTMOUSE
  670. | WINDOWCLOSE
  671. | SMART_REFRESH,
  672.  
  673.   &bool2_gad,             /* First gadget in list                          */
  674.   NULL,                  /* User checkmark                                */
  675.   "Fun with Gadgets",    /* Window Title                                  */
  676.   NULL,                  /* Pointer to screen (Set later)                 */
  677.   NULL,                  /* Pointer to superbitmap                        */
  678.   0, 0, 320, 186,        /* Ignored because not sizeable                  */
  679.   WBENCHSCREEN,          /* Using the Workbench screen                    */
  680.   };
  681.  
  682. /***************************************************************************
  683.                  M A I N     P R O G R A M     M O D U L E
  684. ***************************************************************************/
  685. main()
  686. {
  687.    ULONG MessageClass;
  688.    USHORT code;
  689.    int good_boy = FALSE;     /*  Be a "Bad boy", and hog the system  **/
  690.  
  691. /***************************************************************************
  692.            Must Initialize the Proportional "Specialinfo" before
  693.       opening up the window.  Init Flags,  and position.
  694. ***************************************************************************/
  695.  
  696.    r_prop.Flags = g_prop.Flags = b_prop.Flags = FREEHORIZ | AUTOKNOB;
  697.    r_prop.HorizBody = g_prop.HorizBody = b_prop.HorizBody = 0x1000;
  698.    r_prop.HorizPot = g_prop.HorizPot = b_prop.HorizPot = 0x8000;
  699.  
  700. /***************************************************************************
  701.            Read in the ligraries,  and set each "read" mask bit.
  702. ***************************************************************************/
  703.  
  704.    if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
  705.    {
  706.       printf("no graphics library!!!\n");
  707.       close_things();
  708.       exit(1);
  709.    }
  710.    mask |= GRAPHICS;
  711.  
  712.  if(!(IntuitionBase = (struct IntuitionBase *)
  713.        OpenLibrary("intuition.library",0)))
  714.    {
  715.       printf("no intuition here!!\n");
  716.       close_things();
  717.       exit(2);
  718.    }
  719.    mask |= INTUITION;
  720.  
  721. /***************************************************************************
  722.                 OPEN UP THE WINDOW ON TOP OF WORKBENCH SCREEN
  723. ***************************************************************************/
  724.  
  725.    if (!(w = (struct Window *)OpenWindow(&nw) ))
  726.    {
  727.       printf("could not open the window\n");
  728.       close_things();
  729.       exit(3);
  730.    }
  731.    mask |= WINDOW;
  732.  
  733. /***************************************************************************
  734.                  INITIALIZATION BEFORE ENTERING MAIN LOOP
  735. ***************************************************************************/
  736.  
  737.    rp = w->RPort;
  738.    RefreshGadgets(&red_gad,w,NULL);
  739.  
  740. /***************************************************************************
  741.                             MAIN EVENT LOOP
  742. ***************************************************************************/
  743.  
  744.    for (;;)
  745.    {
  746.  
  747.       if (message = (struct IntuiMessage *)GetMsg(w->UserPort))  {
  748.         MessageClass = message->Class;
  749.         code = message->Code;
  750.         ReplyMsg(message);
  751.         switch (MessageClass) {
  752.  
  753.            case GADGETUP    :
  754.            case GADGETDOWN  : do_gadgets(message, w);
  755.                               break;
  756.  
  757.            case CLOSEWINDOW : close_things();
  758.                               exit(0);
  759.                               break;
  760.            case MOUSEBUTTONS: break;
  761.         }   /* Case */
  762.       }  /* if */
  763.    }  /* for */
  764. } /* main */
  765. /***************************************************************************
  766.                            HANDLE THE GADGETS
  767. ***************************************************************************/
  768. do_gadgets (mes, win)
  769.  
  770. struct IntuiMessage *mes;
  771. struct Window *win;
  772. {
  773.         struct Gadget *igad;     /* Ptr to gadget that Intuition found    */
  774.         int  gadgid;             /* ID Code identifying which gadget      */
  775.         ULONG val;
  776.  
  777.      igad = (struct Gadget *) mes->IAddress;      /* Ptr to a gadget      */
  778.         gadgid = igad->GadgetID;    /* My own personal code for this gad  */
  779.         val = (ULONG)TexString.LongInt;
  780.         switch(gadgid) {
  781.  
  782.             case GREEN_GADGET: break;
  783.             case BLUE_GADGET : break;
  784.             case TEX_GAD     : printf("got here ...\n");
  785.                                printf("val = %ld\n", val);
  786.                                break;
  787.         }
  788. }
  789.  
  790.  
  791. /***************************************************************************
  792.                           CLOSE EVERYTHING DOWN
  793. ***************************************************************************/
  794.  
  795. close_things()
  796. {
  797.    if (mask & WINDOW)    CloseWindow(w);
  798.    if (mask & GRAPHICS)  CloseLibrary(GfxBase);
  799.    (void) OpenWorkBench();
  800.    if (mask & INTUITION) CloseLibrary(IntuitionBase);
  801. }
  802.  
  803.   To use this program,  from CLI,  type: gad > ser:  Then connect serial
  804. to a terminal or another computer.   This sends the printf's thru the
  805. serial port.  Type numeric text in the text window above,  and note the
  806. output.    You COULD just type GAD.   It will output into the CLI window.
  807.  
  808.  
  809.  
  810.  
  811. From dale@amiga.UUCP (Dale Luck) Thu Dec 12 22:34:18 1985
  812. Relay-Version: version B 2.10.2 9/18/84; site gumby.UUCP
  813. Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site amiga.amiga.UUCP
  814. Path: gumby!uwvax!harvard!talcott!panda!genrad!decvax!decwrl!pyramid!amiga!dale
  815. From: dale@amiga.UUCP (Dale Luck)
  816. Newsgroups: net.micro.amiga
  817. Subject: Re: Fun with gadgets
  818. Message-ID: <394@amiga.amiga.UUCP>
  819. Date: 13 Dec 85 04:34:18 GMT
  820. Date-Received: 14 Dec 85 03:46:36 GMT
  821. References: <338@well.UUCP>
  822. Reply-To: dale@tooter.UUCP (Dale Luck)
  823. Organization: Commodore-Amiga Inc., 983 University Ave #D, Los Gatos CA 95030
  824. Lines: 31
  825.  
  826. In article <338@well.UUCP> crunch@well.UUCP (John Draper) writes:
  827. >/***************************************************************************
  828. >                            MAIN EVENT LOOP
  829. >***************************************************************************/
  830. >   for (;;)
  831. >   {
  832. >      if (message = (struct IntuiMessage *)GetMsg(w->UserPort))  {
  833. >        MessageClass = message->Class;
  834. >        code = message->Code;
  835. >        ReplyMsg(message);
  836. >        switch (MessageClass) {
  837. >        }   /* Case */
  838. >      }  /* if */
  839. >   }  /* for */
  840. >} /* main */
  841.    This is similar to the loop I had in the dot.c program
  842.    If your program does need to do anything while waiting for
  843.    messages though you should use
  844.  
  845.         for (;;)
  846.         {
  847.                 Wait(1<<w->UserPort->mp_SigBit);        /* wake up when message there */
  848.                 if (message = (......
  849.                         etc.
  850.         }
  851.  
  852.         This will be much more fair to those other programs and to intuition
  853.         as well.
  854.  
  855.  
  856. From jimm@amiga.UUCP (Jim Mackraz) Fri Dec 13 13:10:32 1985
  857. Relay-Version: version B 2.10.2 9/18/84; site gumby.UUCP
  858. Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site amiga.amiga.UUCP
  859. Path: gumby!uwvax!harvard!talcott!panda!genrad!decvax!decwrl!pyramid!amiga!jimm
  860. From: jimm@amiga.UUCP (Jim Mackraz)
  861. Newsgroups: net.micro.amiga
  862. Subject: IntuiCorrections to Draper and Luck examples
  863. Message-ID: <397@amiga.amiga.UUCP>
  864. Date: 13 Dec 85 19:10:32 GMT
  865. Date-Received: 14 Dec 85 11:28:16 GMT
  866. Reply-To: jimm@homer.UUCP (Jim Mackraz)
  867. Organization: Commodore-Amiga Inc., 983 University Ave #D, Los Gatos CA 95030
  868. Lines: 99
  869.  
  870.  
  871.     Hello net.micro.amiga, and thank you John Draper for forwarding the 
  872.     cause of IntuiEducation.  Dale Luck posted a comment on John's main
  873.     processing loop, but his correction itself was slightly in error.
  874.  
  875.     Furthermore, John commits another common error in his example, duplicated
  876.     below.
  877.  
  878.    EXAMPLE 1 ************ John D's example
  879.    for (;;)
  880.    {
  881.  
  882.       if (message = (struct IntuiMessage *)GetMsg(w->UserPort))  {
  883.         MessageClass = message->Class;
  884.         code = message->Code;
  885.         ReplyMsg(message);
  886.         switch (MessageClass) {
  887.  
  888.            case GADGETUP    :
  889.            case GADGETDOWN  : do_gadgets(message, w);
  890.                               break;
  891.  
  892.            case CLOSEWINDOW : close_things();
  893.                               exit(0);
  894.                               break;
  895.            case MOUSEBUTTONS: break;
  896.         }   /* Case */
  897.       }  /* if */
  898.    }  /* for */
  899.  
  900.     COMMENTS ********
  901.  
  902. As Dale pointed out, a polling loop on the message port is not a proper 
  903. multitasking way to behave.  A more subtle error: note that the message is 
  904. replied to before its contents is used in do_gadgets().  A general principle 
  905. (metaphor by bobp) applies: A Message is a license to use a portion of the 
  906. sender's data space, which no longer applies after the message is Reply'd.  
  907. In this case, Intuition will reuse the message, its contents will change, and 
  908. do_gadgets() may be confused, or crashed, if this happens.
  909.  
  910.     ** IMPORTANT ****
  911.  
  912. I personally like the way John caches the code of the message, and replies as 
  913. soon as possible.  This might prevent Intuition from allocating another 
  914. message for this window if it needs to send another, but the savings are 
  915. marginal.  With the exception of the very dangerous MENUVERIFY, REQVERIFY, 
  916. and SIZEVERIFY messages, it doesn't really matter much if you Reply() before 
  917. or after you use the data in the message.  HOWEVER, be careful about your 
  918. caching.  In particular, IAddress is not guaranteed to hold a reasonable 
  919. value if it is not defined for the particular class of message.
  920.  
  921. So if you try to stash the Gadget ID
  922.  
  923.         ((struct Gadget *)message->IAddress)->GadgetID
  924.  
  925. at the same place John stashes the class and code, and if the class is not 
  926. GADGETUP or GADGETDOWN, you may get an address error (Guru Meditation 
  927. 00000003.<your task here>).  Check the Intuition Manual for the exact times 
  928. that IAddress is used and therefore guaranteed vaild.
  929.  
  930.  
  931.    EXAMPLE 2 ************ Dale's correction to busy loop
  932.  
  933.     for (;;)
  934.     {
  935.             Wait(1<<w->UserPort->mp_SigBit);    /* wake up when message there */
  936.             if (message = (......
  937.                     etc.
  938.     }
  939.  
  940.     COMMENTS *******
  941.  
  942. This demonstrates the spirit of the block-until-message approach, but makes a 
  943. subtle error: Messages queue, while Signals do not.  Therefore, if two 
  944. messages arrive while you are in the body of the loop, when you Wait() you 
  945. will not sleep (signal has already been posted with the arrival of the 
  946. messages), but will process only one message.  Next time you Wait(), you will 
  947. sleep although there is a message in the queue.
  948.  
  949.    EXAMPLE 3 ************  What I use.
  950.  
  951.     FOREVER /* define as for(;;) in intuition.h */
  952.     {
  953.         if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
  954.         {
  955.             Wait(1<<window->UserPort->mp_SigBit);
  956.             continue;
  957.         }
  958.         ...... etc.  ...
  959.     }
  960.  
  961. COMMENTS ***** You may feel free to use any flow of control you like, of 
  962. course.  I think I chose this one because it was different than the first 
  963. solution I saw.
  964.  
  965. GENERAL ***** I want to thank John again for his contributions.  Unless I 
  966. missed something, the remainder of his posting was accurate and clear. I'm 
  967. the new guy at Amiga Software, and my responsibilities include maintenance 
  968. and enhancement of Intuition.  I welcome all questions and suggestions and 
  969. comments.  We have trouble mailing through ARPAnet gateways, so include your 
  970. phone number or USnail address, if you might want a direct reply.
  971.  
  972. It is my hope that I can also provide some examples for new Intuition and 
  973. Amiga application programmers, but time ..., you know.
  974.  
  975.                                 {hplabs,decwr}!pyramid!amiga!jimm
  976.  
  977.  
  978.